# AudioPlayScreen - This screen displays information of currently playing audio
# Copyright (C) 2007 Lauri Taimila
# 
# Entertainer is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# Entertainer is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

__licence__ = "GPLv2"
__copyright__ = "2007, Lauri Taimila"
__author__ = "Lauri Taimila <lauri@taimila.com>"

import os
import gtk
import pango
import gobject
import clutter

from frontend.user_event import UserEvent
from frontend.gui.screens.screen import Screen
from frontend.gui.transitions.transition import Transition

# Widgets
from frontend.gui.widgets.tabs_menu import TabsMenu
from frontend.gui.widgets.text_menu import TextMenu
from frontend.gui.widgets.image_menu import ImageMenu

from frontend.gui.widgets.scroll_area import ScrollArea
from frontend.gui.widgets.progress_bar import ProgressBar
from frontend.gui.widgets.eyecandy_texture import EyeCandyTexture
from frontend.gui.widgets.loading_animation import LoadingAnimation

from frontend.gui.tabs.tab import Tab
from frontend.gui.widgets.tab_group import TabGroup

from frontend.gui.widgets.text_menu_item import TextMenuItem
from frontend.gui.widgets.image_menu_item import ImageMenuItem
#from frontend.gui.widgets.justified_text_menu_item import JustifiedTextMenuItem

#from frontend.gui.widgets.list_indicator import ListIndicator

# Music library
from frontend.medialibrary.music import MusicLibrary
from frontend.medialibrary.music import Track
from frontend.medialibrary.music import Album

class AudioPlayScreen(Screen):
    """
    AudioPlayScreen
    
    Screen that displays information of currently playing audio track.
    """
    
    def __init__(self, ui, frontend, track):
        """
        Initialize screen
        
        @param ui: UserInterface object
        @param frontend: FrontendClient object
        @param track: Track object (We display information of this track)
        """
        self.group = clutter.Group()
        Screen.__init__(self, ui.STAGE_WIDTH, ui.STAGE_HEIGHT)
        
        self.ui = ui
        self.frontend = frontend
        self.player = ui.get_media_player()
        self.theme = frontend.getTheme()
        self.library = self.frontend.get_music_library()
        self.track = track
        self.album = track.get_album()
        
        # Create album art (this is displayed on all tab pages
        if(self.album.has_album_art()):
            pixbuf = gtk.gdk.pixbuf_new_from_file(self.album.get_album_art_url())
        else:
            pixbuf = gtk.gdk.pixbuf_new_from_file(self.theme.getImage("default_album_art"))
        self.art = EyeCandyTexture(pixbuf, self.ui.x(0.3148), self.ui.y(0.5599))
        self.art.set_position(self.ui.get_abs_x_pos(0.1),self.ui.get_abs_y_pos(0.22))
        self.art.set_rotation(clutter.Y_AXIS, 25, 0, 0, 0)
        self.art.show()
        self.group.add(self.art)
        
        # Tabs
        self.tab_group = TabGroup(0.95, 0.13, self.theme.getColor("title"))
        tab1 = self._create_currently_playing_tab()
        tab2 = self._create_lyrics_tab()
        tab3 = self._create_playlist_tab()
        self.tab_group.add_tab(tab1)
        self.tab_group.add_tab(tab2)
        self.tab_group.add_tab(tab3)
        self.tab_group.set_y(self.ui.y(0.1))
        self.tab_group.set_anchor_point_from_gravity(clutter.GRAVITY_CENTER)
        self.tab_group.set_x(self.ui.x(0.5))
        self.tab_group.show()
        self.tab_group.set_active(True)
        self.group.add(self.tab_group)

        self.group.add(tab1)
        self.group.add(tab2)
        self.group.add(tab3)

        self.group.show()
        ui.getStage().add(self.group)
        
        self.ui.get_media_player().set_media(self.track)
        self.ui.get_media_player().play()
        gobject.timeout_add(50, self._update_progress_bar) # 1/4 sec
    
    def _create_currently_playing_tab(self):
        """
        Create a tab that shows information on currenlty playing audio track.
        """
        currently_playing_tab = Tab("Currently playing")
        
        # Track name
        track_label = clutter.Label()
        track_label.set_name("track_label")
        track_label.set_font_name(self.theme.getFont() + " " + str(self.ui.y(0.04948)) + "px")
        track_label.set_color(self.theme.getColor("text"))
        if self.track.get_tracknumber() == 0:
            track_label.set_text(str(self.track.get_title()))
        else:
            track_label.set_text(str(self.track.get_tracknumber()) + ". " + self.track.get_title())
        track_label.set_size(self.ui.x(0.4978), self.ui.y(0.06510))
        track_label.set_position(self.ui.x(0.5), self.ui.y(0.33))
        track_label.set_ellipsize(pango.ELLIPSIZE_END)
        track_label.set_line_wrap(False)
        track_label.show()
        currently_playing_tab.add(track_label)
        
        # Album name
        album_label = clutter.Label()
        album_label.set_name("album_label")
        album_label.set_font_name(self.theme.getFont() + " " + str(self.ui.y(0.0416)) + "px")
        album_label.set_color(self.theme.getColor("subtitle"))
        if self.album.get_year() != 0:
            album_label.set_text("From " + self.album.get_title() + ", " + str(self.album.get_year()))
        else:
            album_label.set_text("From " + self.album.get_title())
        album_label.set_size(self.ui.x(0.4978), self.ui.y(0.06510))
        album_label.set_position(self.ui.x(0.5), self.ui.y(0.43))
        album_label.set_ellipsize(pango.ELLIPSIZE_END)
        album_label.set_line_wrap(False)
        album_label.show()
        currently_playing_tab.add(album_label)
        
        # Artist name
        artist_label = clutter.Label()
        artist_label.set_name("artist_label")
        artist_label.set_font_name(self.theme.getFont() + " " + str(self.ui.y(0.0416)) + "px")
        artist_label.set_color(self.theme.getColor("subtitle"))
        artist_label.set_text("By " + self.album.get_artist())
        artist_label.set_size(self.ui.x(0.4978), self.ui.y(0.06510))
        artist_label.set_position(self.ui.x(0.5), self.ui.y(0.53))
        artist_label.set_ellipsize(pango.ELLIPSIZE_END)
        artist_label.set_line_wrap(False)
        artist_label.show()
        currently_playing_tab.add(artist_label)
        
        # Current position as time stamp
        current_pos = clutter.Label()
        current_pos.set_name("current_pos")
        current_pos.set_font_name(self.theme.getFont() + " " + str(self.ui.y(0.0365)) + "px")
        current_pos.set_color(self.theme.getColor("title"))
        current_pos.set_text("00:00")
        current_pos.set_position(self.ui.x(0.5), self.ui.y(0.665))
        current_pos.show()
        currently_playing_tab.add(current_pos)
        
        progress_bar = ProgressBar(self.ui.x(0.3001), self.ui.y(0.03906), self.theme.getColor("title"))
        progress_bar.set_name("progress_bar")
        progress_bar.set_position(self.ui.x(0.561), self.ui.y(0.667))
        progress_bar.show()
        currently_playing_tab.add(progress_bar)
        
        track_length = clutter.Label()
        track_length.set_name("track_length")
        track_length.set_font_name(self.theme.getFont() + " " + str(self.ui.y(0.0365)) + "px")
        track_length.set_color(self.theme.getColor("title"))
        track_length.set_text(self.track.get_length_string())
        track_length.set_position(self.ui.x(0.8712), self.ui.y(0.665))
        track_length.show()
        currently_playing_tab.add(track_length)
        
        return currently_playing_tab

    def _update_progress_bar(self):
        """
        Update progress bar
        """
        progress_bar = self.tab_group.get_tab_by_index(0).find_child_by_name("progress_bar")
        current_pos = self.tab_group.get_tab_by_index(0).find_child_by_name("current_pos")
        progress_bar.set_progress(self.player.get_media_position())
        current_pos.set_text(self.player.get_media_position_string())
        return True
    
    def _create_lyrics_tab(self):
        """
        Create a tab that displays track lyrics. This tab displays loading
        animation until lyrics are available. Lyrics are searched from the
        Internet if local lyrics doesn't exists.
        """
        lyrics_tab = Tab("Lyrics")

        if self.track.has_lyrics():
            lyrics = clutter.Label()
            lyrics.set_name("lyrics")
            lyrics.set_font_name(self.theme.getFont() + " " + str(self.ui.y(0.0365)) + "px")
            lyrics.set_color(self.theme.getColor("subtitle"))
            lyrics.set_text(self.track.get_lyrics())
            lyrics.set_line_wrap_mode(pango.WRAP_WORD)
            lyrics.set_line_wrap(True)
            lyrics.set_width(self.ui.x(0.366))
            
            lyrics_area = ScrollArea(self.ui.x(0.4), self.ui.y(0.57), self.theme)
            lyrics_area.set_name("lyrics_area")
            lyrics_area.set_step_size(self.ui.y(0.03906))
            lyrics_area.set_content(lyrics)
            lyrics_area.set_position(self.ui.x(0.5), self.ui.y(0.23))
            lyrics_area.show()
            lyrics_tab.add(lyrics_area)
        else:
            # Display throbber animation while searching for lyrics
            white = clutter.Color(255,255,255,255)
            gray = clutter.Color(128,128,128,128)
            throbber = LoadingAnimation(50, white, gray)
            throbber.set_name("throbber")
            throbber.set_position(self.ui.x(0.7), self.ui.y(0.5))
            throbber.show()
            lyrics_tab.add(throbber)
            self.track.fetch_lyrics(self._lyrics_search_callback)
            
        return lyrics_tab
    
    def _lyrics_search_callback(self, lyrics_text):
        """
        This function is called when lyrics search is over.
        @param lyrics: Lyrics or None if lyrics weren't found
        """
        #TODO: We could smoothly fade away throbber
        lyrics_tab = self.tab_group.get_tab_by_index(1)
        lyrics_tab.find_child_by_name("throbber").hide()
        
        if lyrics_text is None:    
            no_lyrics = clutter.Label()
            no_lyrics.set_name("no_lyrics")
            no_lyrics.set_font_name(self.theme.getFont() + " " + str(self.ui.y(0.0365)) + "px")
            no_lyrics.set_color(self.theme.getColor("title"))
            no_lyrics.set_text("No lyrics for this track")
            no_lyrics.set_anchor_point_from_gravity(clutter.GRAVITY_CENTER)
            no_lyrics.set_position(self.ui.x(0.7), self.ui.y(0.5))
            no_lyrics.show()
            lyrics_tab.add(no_lyrics)
        else:
            lyrics = clutter.Label()
            lyrics.set_font_name(self.theme.getFont() + " " + str(self.ui.y(0.0365)) + "px")
            lyrics.set_color(self.theme.getColor("subtitle"))
            lyrics.set_text(lyrics_text)
            lyrics.set_line_wrap_mode(pango.WRAP_WORD)
            lyrics.set_line_wrap(True)
            lyrics.set_width(self.ui.x(0.366))
            
            lyrics_area = ScrollArea(self.ui.x(0.4), self.ui.y(0.57), self.theme)
            lyrics_area.set_name("lyrics_area")
            lyrics_area.set_step_size(self.ui.y(0.03906))
            lyrics_area.set_content(lyrics)
            lyrics_area.set_position(self.ui.x(0.5), self.ui.y(0.23))
            lyrics_area.show()
            lyrics_tab.add(lyrics_area)
            self.library.save_lyrics(self.track, lyrics_text)
    
    def _create_playlist_tab(self):
        """
        Create a tab that displays tracks on current playlist.
        """
        playlist_tab = Tab("Current playlist")
        return playlist_tab
    
    def update(self, track):
        """
        This is called when track changes.
        @param track: Currently playing track
        """
        self.track = track
        self.album = track.get_album()
        
        if self.track.get_tracknumber() == 0:
            self.track_label.set_text(str(self.track.get_title()))
        else:
            self.track_label.set_text(str(self.track.get_tracknumber()) + ". " + self.track.get_title())
        
        if self.album.get_year() != 0:
            self.album_label.set_text("From " + self.album.get_title() + ", " + str(self.album.get_year()))
        else:
            self.album_label.set_text("From " + self.album.get_title())
        
        self.artist_label.set_text("By " + self.album.get_artist())
        self.current_pos.set_text("00:00")
        self.track_length.set_text(self.track.get_length_string())
        self.progress_bar.set_progress(0)
        
    def get_group(self):
        """
        Get all actors of the screen.
        @return clutter.Group 
        """
        return self.group

    def get_type(self):
        """Return screen type."""
        return Screen.NORMAL
    
    def get_name(self):
        """Return screen name (human readble)"""
        return "AudioPlayScreen"
    
    def handle_user_event(self, event):   
        """ 
        Handle screen specific user events
        @param event: UserEvent object
        """
        type = event.get_type()

        if type == UserEvent.NAVIGATE_UP:
            tab = self.tab_group.get_current_tab()
            
            # If we are on Lyrics tab
            if tab.get_title() == "Lyrics" and not self.tab_group.is_active():
                area = tab.find_child_by_name("lyrics_area")
                if area.is_active() and area.get_offset() == 0:
                    area.set_active(False)
                    self.tab_group.set_active(True)
                elif area.is_active():
                    area.scroll_up()
                
        elif type == UserEvent.NAVIGATE_DOWN:
            tab = self.tab_group.get_current_tab()
            
            # If we are on Lyrics tab
            if tab.get_title() == "Lyrics":
                area = tab.find_child_by_name("lyrics_area")
                if self.tab_group.is_active():
                    self.tab_group.set_active(False)
                    area = tab.find_child_by_name("lyrics_area")
                    try:
                        area.set_active(True)
                    except:
                        pass # There is no lyrics area since we are still searching for lyrics
                else:
                    area.scroll_down()
        
        elif type == UserEvent.NAVIGATE_LEFT:
            if self.tab_group.is_active():
                self.tab_group.handle_user_event(event)
        
        elif type == UserEvent.NAVIGATE_RIGHT:
            if self.tab_group.is_active():
                self.tab_group.handle_user_event(event)
        
        elif type == UserEvent.NAVIGATE_SELECT:
            pass


